import * as THREE from 'three';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';
import {TWEEN} from "three/examples/jsm/libs/tween.module.min";
import Stats from 'three/examples/jsm/libs/stats.module.js';
import {GUI} from 'three/examples/jsm/libs/dat.gui.module.js';
import {baseUrl} from '../../js/base.js'
import '../../css/base.css'
import {Face3, Geometry} from "three/examples/jsm/deprecated/Geometry";


let canvas = document.getElementById("canvas")
let renderer, scene, camera;
let stats

let group, face

let orbitControls
let mouse = new THREE.Vector2(), point = null;
let raycaster = new THREE.Raycaster();
const body = document.body

const params = {
    open: false
}

let pointsList = [], floorName = '', drawObj

const floorParams = []

function initCSR() {
    const w = canvas.offsetWidth;
    const h = canvas.offsetHeight;

    camera = new THREE.PerspectiveCamera(75, w / h, 0.1, 10000)
    camera.position.set(0, 30, 50)

    scene = new THREE.Scene()

    renderer = new THREE.WebGLRenderer({canvas, antialias: true, alpha: false});
    camera.updateProjectionMatrix();
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(w, h, false)
}

function initLight() {
    const ambientLight = new THREE.AmbientLight(0xffffff, 2);
    scene.add(ambientLight)

    const directionalLight = new THREE.DirectionalLight(0xFFFFFF, .5);
    directionalLight.position.set(1, 1, 1)
    scene.add(directionalLight)
}

function initModel() {
    let textureLoader = new THREE.TextureLoader();
    let texture = textureLoader.load(baseUrl + 'static/images/vrLook/O1_f.webp')
    texture.wrapS = texture.wrapT = THREE.MirroredRepeatWrapping
    texture.repeat.set(32, 32)
    const geometry = new THREE.BoxGeometry(50, 3, 50);
    group = new THREE.Group();
    group.position.setY(1.5)
    group.name = 'group'
    for (let i = 0; i < 8; i++) {
        const material = new THREE.MeshPhongMaterial({
            map: texture,
            side: THREE.BackSide,
            transparent: true,
            depthTest: true
        });
        const floor = new THREE.Mesh(geometry, material);
        floor.name = 'floor_' + i
        floor.position.setY(i * 3.8 - 7.6)
        floorParams.push({
            name: floor.name,
            object: floor,
            close: i * 3.8,
            open: i * 16
        })
        group.add(floor);
    }
    scene.add(group)

    // scene.add(new THREE.AxesHelper(100))
    drawFace([
        [0, 0, 0],
        [10, 0, 0],
        [10, 0, 10],
        [0, 0, 10]
    ])
}

function drawFace(pointList) {
    const geometry = new Geometry();

    pointList.forEach(points => {
        geometry.vertices.push(new THREE.Vector3(...points))
    })
    const vector3 = new THREE.Vector3();
    const color = new THREE.Color();
    for (let i = 2; i < pointList.length; i++) {
        geometry.faces.push(new Face3(0, i - 1, i, vector3, color, i));
    }

    let material = new THREE.MeshBasicMaterial({
        color: 0xff0000,
        transparent: true,
        opacity: 1,
        side: THREE.DoubleSide,
        depthTest: false
    });
    face = new THREE.Mesh(geometry, material);
    console.log(face)
    group.add(face)
}

function initControls() {
    orbitControls = new OrbitControls(camera, canvas);
    orbitControls.target.set(0, 0, 0)
}

function initHelper() {
    stats = new Stats()
    body.appendChild(stats.domElement)

    const gui = new GUI();

    Object.keys(params).forEach(key => {
        gui.add(params, key).onChange((boolean) => {
            openFloor(boolean)
        })
    })
}

function openFloor(boolean) {
    console.log(boolean)
    console.log(floorParams[0].object);
    floorParams.forEach((value, index) => {
        new TWEEN.Tween({position: !boolean ? value.open : value.close})
            .to({position: boolean ? value.open : value.close}, 500)
            .onUpdate(val => {
                value.object.position.setY(val.position)
            }).start();
    })

}

function onWindowResize() {
    renderer.setPixelRatio(window.devicePixelRatio);
    const width = canvas.offsetWidth;
    const height = canvas.offsetHeight;
    camera.aspect = width / height;
    camera.updateProjectionMatrix();
    renderer.setSize(width, height, false);
} // 控制窗口大小

function render() {
    if (orbitControls) orbitControls.update()
    if (TWEEN) TWEEN.update()
    renderer.render(scene, camera)
    if (stats) stats.update();
}

function animation() {
    requestAnimationFrame(animation)
    render()
}

function addEL() {
    window.addEventListener('resize', onWindowResize);
    canvas.addEventListener('pointerdown', mouseDown, false)
    canvas.addEventListener('pointermove', mouseMove, false)
    canvas.addEventListener('pointerup', mouseUp, false)
}

function mouseDown(e) {
    mouse.x = (e.offsetX / canvas.offsetWidth) * 2 - 1;
    mouse.y = -(e.offsetY / canvas.offsetHeight) * 2 + 1;

    raycaster.setFromCamera(mouse, camera);
    let intersectObjects = raycaster.intersectObjects(scene.children, true);
    if (!intersectObjects.length) return
    const obj = intersectObjects[0]
    point = obj.point
    console.log(point)


    if (!floorName) return
    if (floorName === obj.object.name) {
        pointsList.push([point.x, point.y, point.z])
    }
}

function mouseMove(e) {
    mouse.x = (e.offsetX / canvas.offsetWidth) * 2 - 1;
    mouse.y = -(e.offsetY / canvas.offsetHeight) * 2 + 1;

    raycaster.setFromCamera(mouse, camera);
    let intersectObjects = raycaster.intersectObjects(scene.children, true);
    if (!intersectObjects.length) return
    const obj = intersectObjects[0]
    floorParams.forEach(value => {
        if (value.name !== obj.object.name) {
            value.object.material.opacity = .6
        } else {
            value.object.material.opacity = 1
        }
    })

    if (!floorName) return
    if (floorName === obj.object.name) {
        point = obj.point
        pointsList.pop()
        pointsList.push([point.x, point.y, point.z])
        group.remove(face)
        drawFace(pointsList)
        console.log(intersectObjects[0].object.name)
    }
}

function mouseUp(e) {
    mouse.x = (e.offsetX / canvas.offsetWidth) * 2 - 1;
    mouse.y = -(e.offsetY / canvas.offsetHeight) * 2 + 1;

    raycaster.setFromCamera(mouse, camera);
    let intersectObjects = raycaster.intersectObjects(scene.children, true);
    if (!intersectObjects.length) return
    const obj = intersectObjects[0]
    console.log(obj)
    if (point.equals(obj.point)) {
        floorName = obj.object.name
        new TWEEN.Tween({setY: group.position.y})
            .to({setY: group.position.y - obj.point.y}, 500)
            .onUpdate(val => {
                group.position.setY(val.setY)
            }).start();
        floorParams.forEach(value => {
            if (value.name !== obj.object.name) {
                value.object.material.opacity = .6
                value.object.scale.set(1, 1, 1)
                value.object.material.color = new THREE.Color()
            } else {
                value.object.material.opacity = 1
                value.object.scale.set(1.1, 1.1, 1.1)
                value.object.material.color = new THREE.Color(0xffffff)
            }
        })
    }


    if (!floorName) return
    if (floorName === obj.object.name) {
        group.remove(face)
        drawFace(pointsList)
    }
}

(() => {
    initCSR();
    initLight();
    initHelper()
    initModel();
    initControls();
    addEL()
    animation();
})();


